home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / pyshared / DistUpgrade / MetaRelease.py < prev    next >
Text File  |  2009-11-02  |  11KB  |  281 lines

  1. # MetaRelease.py 
  2. #  
  3. #  Copyright (c) 2004,2005 Canonical
  4. #  
  5. #  Author: Michael Vogt <michael.vogt@ubuntu.com>
  6. #  This program is free software; you can redistribute it and/or 
  7. #  modify it under the terms of the GNU General Public License as 
  8. #  published by the Free Software Foundation; either version 2 of the
  9. #  License, or (at your option) any later version.
  10. #  This program is distributed in the hope that it will be useful,
  11. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. #  GNU General Public License for more details.
  14. #  You should have received a copy of the GNU General Public License
  15. #  along with this program; if not, write to the Free Software
  16. #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  17. #  USA
  18.  
  19. import apt_pkg
  20. import ConfigParser
  21. import httplib
  22. import rfc822
  23. import os
  24. import string
  25. import sys
  26. import time
  27. import thread
  28. import urllib2
  29.  
  30. from subprocess import Popen,PIPE
  31.  
  32. from utils import *
  33.  
  34. class Dist(object):
  35.     def __init__(self, name, version, date, supported):
  36.         self.name = name
  37.         self.version = version
  38.         self.date = date
  39.         self.supported = supported
  40.         self.releaseNotesURI = None
  41.         self.upgradeTool = None
  42.         self.upgradeToolSig = None
  43.  
  44. class MetaReleaseCore(object):
  45.     """
  46.     A MetaReleaseCore object astracts the list of released 
  47.     distributions. 
  48.     """
  49.  
  50.     DEBUG = "DEBUG_UPDATE_MANAGER" in os.environ
  51.  
  52.     # some constants
  53.     CONF = "/etc/update-manager/release-upgrades"
  54.     CONF_METARELEASE = "/etc/update-manager/meta-release"
  55.  
  56.     def __init__(self, 
  57.                  useDevelopmentRelease=False, 
  58.                  useProposed=False,
  59.                  forceLTS=False):
  60.         self._debug("MetaRelease.__init__() useDevel=%s useProposed=%s" % (useDevelopmentRelease, useProposed))
  61.         # information about the available dists
  62.         self.downloading = True
  63.         self.new_dist = None
  64.         self.current_dist_name = get_dist()
  65.         self.no_longer_supported = None
  66.  
  67.         # default (if the conf file is missing)
  68.         self.METARELEASE_URI = "http://changelogs.ubuntu.com/meta-release"
  69.         self.METARELEASE_URI_LTS = "http://changelogs.ubuntu.com/meta-release-lts"
  70.         self.METARELEASE_URI_UNSTABLE_POSTFIX = "-development"
  71.         self.METARELEASE_URI_PROPOSED_POSTFIX = "-development"
  72.  
  73.         # check the meta-release config first
  74.         parser = ConfigParser.ConfigParser()
  75.         if os.path.exists(self.CONF_METARELEASE):
  76.             try:
  77.                 parser.read(self.CONF_METARELEASE)
  78.             except ConfigParser.Error, e:
  79.                 sys.stderr.write("ERROR: failed to read '%s':\n%s" % (
  80.                         self.CONF_METARELEASE, e))
  81.                 return
  82.             # make changing the metarelease file and the location
  83.             # for the files easy
  84.             if parser.has_section("METARELEASE"):
  85.                 sec = "METARELEASE"
  86.                 for k in ["URI",
  87.                           "URI_LTS",
  88.                           "URI_UNSTABLE_POSTFIX",
  89.                           "URI_PROPOSED_POSTFIX"]:
  90.                     if parser.has_option(sec, k):
  91.                         self._debug("%s: %s " % (self.CONF_METARELEASE,
  92.                                                  parser.get(sec,k)))
  93.                         setattr(self, "%s_%s" % (sec, k), parser.get(sec, k))
  94.  
  95.         # check the config file first to figure if we want lts upgrades only
  96.         parser = ConfigParser.ConfigParser()
  97.         if os.path.exists(self.CONF):
  98.             try:
  99.                 parser.read(self.CONF)
  100.             except ConfigParser.Error, e:
  101.                 sys.stderr.write("ERROR: failed to read '%s':\n%s" % (
  102.                         self.CONF, e))
  103.                 return
  104.             # now check which specific url to use
  105.             if parser.has_option("DEFAULT","Prompt"):
  106.                 type = parser.get("DEFAULT","Prompt").lower()
  107.                 if (type == "never" or type == "no"):
  108.                     # nothing to do for this object
  109.                     # FIXME: what about no longer supported?
  110.                     self.downloading = False
  111.                     return
  112.                 elif type == "lts":
  113.                     self.METARELEASE_URI = self.METARELEASE_URI_LTS
  114.         # needed for the _tryUpgradeSelf() code in DistUpgradeController
  115.         if forceLTS:
  116.             self.METARELEASE_URI = self.METARELEASE_URI_LTS
  117.         # devel and proposed "just" change the postfix
  118.         if useDevelopmentRelease:
  119.             self.METARELEASE_URI += self.METARELEASE_URI_UNSTABLE_POSTFIX
  120.         elif useProposed:
  121.             self.METARELEASE_URI += self.METARELEASE_URI_PROPOSED_POSTFIX
  122.  
  123.         self._debug("metarelease-uri: %s" % self.METARELEASE_URI)
  124.         self.metarelease_information = None
  125.         if not self._buildMetaReleaseFile():
  126.             self._debug("_buildMetaReleaseFile failed")
  127.             return
  128.         # we start the download thread here and we have a timeout
  129.         t=thread.start_new_thread(self.download, ())
  130.         #t=thread.start_new_thread(self.check, ())
  131.  
  132.     def _buildMetaReleaseFile(self):
  133.         # build the metarelease_file name
  134.         self.METARELEASE_FILE = os.path.join("/var/lib/update-manager/",
  135.                                             os.path.basename(self.METARELEASE_URI))
  136.         # check if we can write to the global location, if not,
  137.         # write to homedir
  138.         try:
  139.             open(self.METARELEASE_FILE,"a")
  140.         except IOError, e:
  141.             path = os.path.expanduser("~/.update-manager-core/")
  142.             if not os.path.exists(path):
  143.         try:
  144.                     os.mkdir(path)
  145.         except OSError, e:
  146.                     sys.stderr.write("mkdir() failed: '%s'" % e)
  147.             return False
  148.             self.METARELEASE_FILE = os.path.join(path,os.path.basename(self.METARELEASE_URI))
  149.         # if it is empty, remove it to avoid I-M-S hits on empty file
  150.         try:
  151.             if os.path.getsize(self.METARELEASE_FILE) == 0:
  152.                 os.unlink(self.METARELEASE_FILE)
  153.         except Exception, e:
  154.             pass
  155.         return True
  156.  
  157.     def dist_no_longer_supported(self, dist):
  158.         """ virtual function that is called when the distro is no longer
  159.             supported
  160.         """
  161.         self.no_longer_supported = dist
  162.     def new_dist_available(self, dist):
  163.         """ virtual function that is called when a new distro release
  164.             is available
  165.         """
  166.         self.new_dist = dist
  167.  
  168.     def parse(self):
  169.         self._debug("MetaRelease.parse()")
  170.         current_dist_name = self.current_dist_name
  171.         self._debug("current dist name: '%s'" % current_dist_name)
  172.         current_dist = None
  173.         dists = []
  174.  
  175.         # parse the metarelease_information file
  176.         index_tag = apt_pkg.ParseTagFile(self.metarelease_information)
  177.         step_result = index_tag.Step()
  178.         while step_result:
  179.             if index_tag.Section.has_key("Dist"):
  180.                 name = index_tag.Section["Dist"]
  181.                 #print name
  182.                 rawdate = index_tag.Section["Date"]
  183.                 date = time.mktime(rfc822.parsedate(rawdate))
  184.                 supported = int(index_tag.Section["Supported"])
  185.                 version = index_tag.Section["Version"]
  186.                 # add the information to a new date object
  187.                 dist = Dist(name, version, date,supported)
  188.                 if index_tag.Section.has_key("ReleaseNotes"):
  189.                     dist.releaseNotesURI = index_tag.Section["ReleaseNotes"]
  190.                 if index_tag.Section.has_key("UpgradeTool"):
  191.                     dist.upgradeTool =  index_tag.Section["UpgradeTool"]
  192.                 if index_tag.Section.has_key("UpgradeToolSignature"):
  193.                     dist.upgradeToolSig =  index_tag.Section["UpgradeToolSignature"]
  194.                 dists.append(dist)
  195.                 if name == current_dist_name:
  196.                     current_dist = dist 
  197.             step_result = index_tag.Step()
  198.  
  199.         # first check if the current runing distro is in the meta-release
  200.         # information. if not, we assume that we run on something not
  201.         # supported and silently return
  202.         if current_dist is None:
  203.             #sys.stderr.write("current dist not found in meta-release file\n")
  204.             return False
  205.  
  206.         # then see what we can upgrade to (only upgrade to supported dists)
  207.         upgradable_to = ""
  208.         for dist in dists:
  209.             if dist.date > current_dist.date and dist.supported == True: 
  210.                 upgradable_to = dist
  211.                 self._debug("new dist: %s" % upgradable_to)
  212.                 break
  213.  
  214.         # only warn if unsupported and a new dist is available (because 
  215.         # the development version is also unsupported)
  216.         if upgradable_to != "" and not current_dist.supported:
  217.             self.dist_no_longer_supported(upgradable_to)
  218.         if upgradable_to != "":
  219.             self.new_dist_available(upgradable_to)
  220.  
  221.         # parsing done and sucessfully
  222.         return True
  223.  
  224.     # the network thread that tries to fetch the meta-index file
  225.     # can't touch the gui, runs as a thread
  226.     def download(self):
  227.         self._debug("MetaRelease.download()")
  228.         lastmodified = 0
  229.         req = urllib2.Request(self.METARELEASE_URI)
  230.         # make sure that we always get the latest file (#107716)
  231.         req.add_header("Cache-Control", "No-Cache")
  232.         req.add_header("Pragma", "no-cache")
  233.         if os.access(self.METARELEASE_FILE, os.W_OK):
  234.             lastmodified = os.stat(self.METARELEASE_FILE).st_mtime
  235.         if lastmodified > 0:
  236.             req.add_header("If-Modified-Since", time.asctime(time.gmtime(lastmodified)))
  237.         try:
  238.             uri=urllib2.urlopen(req)
  239.             # sometime there is a root owned meta-relase file
  240.             # there, try to remove it so that we get it
  241.             # with proper permissions
  242.             if (os.path.exists(self.METARELEASE_FILE) and
  243.                 not os.access(self.METARELEASE_FILE,os.W_OK)):
  244.                 try:
  245.                     os.unlink(self.METARELEASE_FILE)
  246.                 except OSError,e:
  247.                     print "Can't unlink '%s' (%s)" % (self.METARELEASE_FILE,e)
  248.             # we may get excpetion here on e.g. disk full
  249.             try:
  250.                 f=open(self.METARELEASE_FILE,"w+")
  251.                 for line in uri.readlines():
  252.                     f.write(line)
  253.                 f.flush()
  254.                 f.seek(0,0)
  255.                 self.metarelease_information=f
  256.             except IOError, e:
  257.                 pass
  258.             uri.close()
  259.         except (urllib2.URLError, httplib.BadStatusLine), e:
  260.             if os.path.exists(self.METARELEASE_FILE):
  261.                 self.metarelease_information=open(self.METARELEASE_FILE,"r")
  262.         # now check the information we have
  263.         if self.metarelease_information != None:
  264.             self._debug("have self.metarelease_information")
  265.             self.parse()
  266.         else:
  267.             self._debug("NO self.metarelease_information")
  268.         self.downloading = False
  269.  
  270.     def _debug(self, msg):
  271.         if self.DEBUG:
  272.             sys.stderr.write(msg+"\n")
  273.  
  274.  
  275. if __name__ == "__main__":
  276.     meta = MetaReleaseCore(False, False)
  277.     
  278.